home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / nt / source.exe / POSIX / MV / MV.C < prev    next >
C/C++ Source or Header  |  1993-06-23  |  9KB  |  382 lines

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Ken Smith of The State University of New York at Buffalo.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifdef DF_POSIX /* DF_MSS */
  38. #include <misc.h>
  39. #include <bsdlib.h>
  40. #endif
  41.  
  42. #ifndef lint
  43. char copyright[] =
  44. "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
  45.  All rights reserved.\n";
  46. #endif /* not lint */
  47.  
  48. #ifndef lint
  49. static char sccsid[] = "@(#)mv.c    5.11 (Berkeley) 4/3/91";
  50. #endif /* not lint */
  51. #ifdef DF_POSIX
  52. #include <sys/cdefs.h>
  53. #else /* DF_DSC: not needed by POSIX */
  54. #include <sys/param.h>
  55. #endif
  56. #ifdef _POSIX_SOURCE
  57. #include <time.h>
  58. #else
  59. #include <sys/time.h>
  60. #endif
  61. #include <sys/wait.h>
  62. #include <sys/stat.h>
  63. #include <fcntl.h>
  64. #include <errno.h>
  65. #include <unistd.h>
  66. #include <stdio.h>
  67. #include <stdlib.h>
  68. #include <string.h>
  69. #include "pathnames.h"
  70.  
  71. #if WIN_NT
  72. int do_move __P((char *, char *));
  73. int fastcopy __P((char *, char *, struct stat *));
  74. int copy __P((char *, char *));
  75. void error __P((char *));
  76. void usage __P((void));
  77. extern int globulate __P((int, int, char **));
  78. extern void deglobulate __P((void));
  79. extern int globulated_argc;
  80. extern char **globulated_argv;
  81. pid_t ppid;
  82. int globulation;
  83. #endif
  84.  
  85. int fflg, iflg;
  86.  
  87. int
  88. #if __STDC__
  89. main (int argc, char **argv)
  90. #else
  91. main(argc, argv)
  92.     int argc;
  93.     char **argv;
  94. #endif
  95. {
  96.     extern char *optarg;
  97.     extern int optind;
  98.     register int baselen, exitval, len;
  99.     register char *p, *endp;
  100.     struct stat sb;
  101.     int ch;
  102. #ifdef _POSIX_SOURCE
  103.     char path[PATH_MAX +1];
  104. #else
  105.     char path[MAXPATHLEN + 1];
  106. #endif
  107.  
  108. #if WIN_NT
  109.     ppid = getppid();
  110.     if (ppid == (pid_t) 1) /* if parent is CMD.EXE */
  111.     {
  112.         globulation = globulate(1, argc, argv);
  113.         if (globulation == 0)
  114.         {
  115.             argc = globulated_argc;
  116.             argv = globulated_argv;
  117.         }
  118.     }
  119. #endif
  120.     while (((ch = getopt(argc, argv, "-if")) != EOF))
  121.         switch((char)ch) {
  122.         case 'i':
  123.             iflg = 1;
  124.             break;
  125.         case 'f':
  126.             fflg = 1;
  127.             break;
  128.         case '-':        /* undocumented; for compatibility */
  129.             goto endarg;
  130.         case '?':
  131.         default:
  132.             usage();
  133.         }
  134. endarg:    argc -= optind;
  135.     argv += optind;
  136.  
  137.     if (argc < 2)
  138.         usage();
  139.  
  140.     /*
  141.      * If the stat on the target fails or the target isn't a directory,
  142.      * try the move.  More than 2 arguments is an error in this case.
  143.      */
  144.     if (stat(argv[argc - 1], &sb) || !S_ISDIR(sb.st_mode)) {
  145.         if (argc > 2)
  146.             usage();
  147. #if WIN_NT
  148.         exitval = do_move(argv[0], argv[1]);
  149.         if (ppid == (pid_t) 1 && globulation == 0)
  150.             deglobulate();
  151.         exit(exitval);
  152. #else
  153.         exit(do_move(argv[0], argv[1]));
  154. #endif
  155.     }
  156.  
  157.     /* It's a directory, move each file into it. */
  158.     (void)strcpy(path, argv[argc - 1]);
  159.     baselen = strlen(path);
  160.     endp = &path[baselen];
  161.     *endp++ = '/';
  162.     ++baselen;
  163.     for (exitval = EXIT_SUCCESS; --argc; ++argv) {
  164.         if ((p = rindex(*argv, '/')) == NULL)
  165.             p = *argv;
  166.         else
  167.             ++p;
  168. #ifdef _POSIX_SOURCE
  169.         if ((baselen + (len = strlen(p))) >= PATH_MAX)
  170. #else
  171.         if ((baselen + (len = strlen(p))) >= MAXPATHLEN)
  172. #endif
  173.             (void)fprintf(stderr,
  174.                 "mv: %s: destination pathname too long\n", *argv);
  175.         else {
  176.             bcopy(p, endp, len + 1);
  177.             exitval |= do_move(*argv, path);
  178.         }
  179.     }
  180. #if WIN_NT
  181.     if (ppid == (pid_t) 1 && globulation == 0)
  182.         deglobulate();
  183. #endif
  184.     return exitval;
  185. }
  186.  
  187. int
  188. #if __STDC__
  189. do_move (char *from, char *to)
  190. #else
  191. do_move(from, to)
  192.     char *from, *to;
  193. #endif
  194. {
  195.     struct stat sb;
  196.     int ask, ch;
  197.  
  198.     /*
  199.      * Check access.  If interactive and file exists, ask user if it
  200.      * should be replaced.  Otherwise if file exists but isn't writable
  201.      * make sure the user wants to clobber it.
  202.      */
  203.     if (!fflg && !access(to, F_OK)) {
  204.         ask = 0;
  205.         if (iflg) {
  206.             (void)fprintf(stderr, "overwrite %s? ", to);
  207.             ask = 1;
  208.         }
  209.         else if (access(to, W_OK) && !stat(to, &sb)) {
  210.             (void)fprintf(stderr, "override mode %o on %s? ",
  211.                 sb.st_mode & 07777, to);
  212.             ask = 1;
  213.         }
  214.         if (ask) {
  215.             if ((ch = getchar()) != EOF && ch != '\n')
  216.                 while (getchar() != '\n');
  217.             if (ch != 'y')
  218.                 return(EXIT_SUCCESS);
  219.         }
  220.     }
  221.     if (!rename(from, to))
  222.         return(EXIT_SUCCESS);
  223.  
  224.     if (errno != EXDEV) {
  225.         (void)fprintf(stderr,
  226.             "mv: rename %s to %s: %s\n", from, to, strerror(errno));
  227.         return(EXIT_FAILURE);
  228.     }
  229.  
  230.     /*
  231.      * If rename fails, and it's a regular file, do the copy internally;
  232.      * otherwise, use cp and rm.
  233.      */
  234.     if (stat(from, &sb)) {
  235.         (void)fprintf(stderr, "mv: %s: %s\n", from, strerror(errno));
  236.         return(EXIT_FAILURE);
  237.     }
  238.     return(S_ISREG(sb.st_mode) ?
  239.         fastcopy(from, to, &sb) : copy(from, to));
  240. }
  241.  
  242. int
  243. #if __STDC__
  244. fastcopy (char *from, char *to, struct stat *sbp)
  245. #else
  246. fastcopy(from, to, sbp)
  247.     char *from, *to;
  248.     struct stat *sbp;
  249. #endif
  250. {
  251.     struct timeval tval[2];
  252.     static u_int blen;
  253.     static char *bp;
  254.     register int nread, from_fd, to_fd;
  255.  
  256.     if ((from_fd = open(from, O_RDONLY, 0)) < 0) {
  257.         error(from);
  258.         return(EXIT_FAILURE);
  259.     }
  260.     if ((to_fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, sbp->st_mode)) < 0) {
  261.         error(to);
  262.         (void)close(from_fd);
  263.         return(EXIT_FAILURE);
  264.     }
  265. /* DF_MSS: st_blksize is not part of the STAT struct; defining preferred blksize to 1024 */
  266. #ifdef DF_POSIX /* DF_MSS */
  267.         if (!blen && !(bp = malloc(blen = /*sbp->st_blksize*/ 1024))) {
  268. #else
  269.         if (!blen && !(bp = malloc(blen = sbp->st_blksize))) {
  270. #endif
  271.         error(NULL);
  272.         return(EXIT_FAILURE);
  273.     }
  274.     while ((nread = read(from_fd, bp, blen)) > 0)
  275.         if (write(to_fd, bp, nread) != nread) {
  276.             error(to);
  277.             goto err;
  278.         }
  279.     if (nread < 0) {
  280.         error(from);
  281. err:        (void)unlink(to);
  282.         (void)close(from_fd);
  283.         (void)close(to_fd);
  284.         return(EXIT_FAILURE);
  285.     }
  286. #ifdef _POSIX_SOURCE /* DF_MSS */
  287.     (void)chown(to, sbp->st_uid, sbp->st_gid);
  288.     (void)chmod(to, sbp->st_mode);
  289. #else
  290.     (void)fchown(to_fd, sbp->st_uid, sbp->st_gid);
  291.     (void)fchmod(to_fd, sbp->st_mode);
  292. #endif
  293.  
  294.     (void)close(from_fd);
  295.     (void)close(to_fd);
  296.  
  297.     tval[0].tv_sec = sbp->st_atime;
  298.     tval[1].tv_sec = sbp->st_mtime;
  299.     tval[0].tv_usec = tval[1].tv_usec = 0;
  300.     (void)utimes(to, tval);
  301.     (void)unlink(from);
  302.     return(EXIT_SUCCESS);
  303. }
  304.  
  305. int
  306. #if __STDC__
  307. copy (char *from, char *to)
  308. #else
  309. copy(from, to)
  310.     char *from, *to;
  311. #endif
  312. {
  313. #if _POSIX_SOURCE
  314.     pid_t pid;
  315.     int status;
  316. #else
  317.     int pid, status;
  318. #endif
  319.  
  320. #ifdef _POSIX_SOURCE /* DF_MSS */
  321.     if (!(pid = fork())) {
  322. #else
  323.     if (!(pid = vfork())) {
  324. #endif
  325.         execl(_PATH_CP, "mv", "-pr", from, to, NULL);
  326.         error(_PATH_CP);
  327. #if WIN_NT
  328.         if (ppid == (pid_t) 1 && globulation == 0)
  329.             deglobulate();
  330. #endif
  331.         _exit(EXIT_FAILURE);
  332.     }
  333.     (void)waitpid(pid, &status, 0);
  334.     if (!WIFEXITED(status) || WEXITSTATUS(status))
  335.         return(EXIT_FAILURE);
  336. #ifdef _POSIX_SOURCE /* DF_MSS */
  337.     if (!(pid = fork())) {
  338. #else
  339.     if (!(pid = vfork())) {
  340. #endif
  341.         execl(_PATH_RM, "mv", "-rf", from, NULL);
  342.         error(_PATH_RM);
  343. #if WIN_NT
  344.         if (ppid == (pid_t) 1 && globulation == 0)
  345.             deglobulate();
  346. #endif
  347.         _exit(EXIT_FAILURE);
  348.     }
  349.     (void)waitpid(pid, &status, 0);
  350.     return(!WIFEXITED(status) || WEXITSTATUS(status));
  351. }
  352.  
  353. void
  354. #if __STDC__
  355. error (char *s)
  356. #else
  357. error(s)
  358.     char *s;
  359. #endif
  360. {
  361.     if (s)
  362.         (void)fprintf(stderr, "mv: %s: %s\n", s, strerror(errno));
  363.     else
  364.         (void)fprintf(stderr, "mv: %s\n", strerror(errno));
  365. }
  366.  
  367. void
  368. #if __STDC__
  369. usage (void)
  370. #else
  371. usage()
  372. #endif
  373. {
  374.     (void)fprintf(stderr,
  375. "usage: mv [-if] src target;\n   or: mv [-if] src1 ... srcN directory\n");
  376. #if WIN_NT
  377.     if (ppid == (pid_t) 1 && globulation == 0)
  378.         deglobulate();
  379. #endif
  380.     exit(EXIT_FAILURE);
  381. }
  382.